#pragma once
#include<iostream>
#include<stdint.h>
#include<functional>
#include<sys/epoll.h>
#include"Log.hpp"
//对监听描述符的封装（用于获取监听描述符的就绪事件情况）
class EventLoop;
//Channel模块,对监听描述符的封装（用于获取监听描述符的就绪事件情况）
class Channel {
    private:
        int _fd;
        EventLoop* _loop;
        uint32_t _events;//监听事件
        uint32_t _revents;//就绪事件
        using EventCallback = std::function<void()>;
        EventCallback _read_callback;//可读事件被触发的回调函数
        EventCallback _write_callback; //可写事件被触发的回调函数
        EventCallback _error_callback; //错误事件被触发的回调函数
        EventCallback _close_callback; //连接断开事件被触发的回调函数
        EventCallback _other_callback; //任意事件被触发的回调函数
    public:
        Channel(EventLoop* loop,int fd): _loop(loop),_fd(fd), _events(0), _revents(0) {}

        EventLoop* GetLoop() { return _loop; }  //获取EventLoop指针

        int Fd() { return _fd; }
        uint32_t GetEvents() { return _events; }//获取监听事件
        void SetRevents(uint32_t revents) { _revents = revents; }//设置就绪事件(由上层接口调用)
        void SetReadCallback(const EventCallback& cb) { _read_callback = cb; }
        void SetWriteCallback(const EventCallback& cb) { _write_callback = cb; }
        void SetErrorCallback(const EventCallback& cb) { _error_callback = cb; }
        void SetCloseCallback(const EventCallback& cb) { _close_callback = cb; }
        void SetOtherCallback(const EventCallback& cb) { _other_callback = cb; }

        //判断是否监控了可读
        bool Readable() { return _events & EPOLLIN; }
        //判断是否监控了可写
        bool Writable() { return _events & EPOLLOUT; }
        
        //设置可读
        void EnableReading() { _events |= EPOLLIN; }
        //设置可写
        void EnableWriting() { _events |= EPOLLOUT; }

        //关闭可读
        void DisableReading() { _events &= ~EPOLLIN; }
        //关闭可写
        void DisableWriting() { _events &= ~EPOLLOUT; }
        //关闭所有事件监控
        void DisableAll() { _events = 0; }

        //处理就绪事件
        void HandleEvent() 
        {
            if(_revents & EPOLLIN && _read_callback){
                _read_callback();
            }else if(_revents & EPOLLOUT && _write_callback){
                _write_callback();
            }else if(_revents & EPOLLHUP && _close_callback){
                _close_callback();
            }else if(_revents & EPOLLERR && _error_callback){
                _error_callback();
            }else{
                if(_other_callback)
                    _other_callback();
                else
                    LOG_ERR("unknown event:");
            }

        }
};